//-*-C++-*-
/***************************************************************************
 *
 *   Copyright (C) 2024 by Jesmigel Cantos
 *   Licensed under the Academic Free License version 2.1
 *
 ***************************************************************************/
// dspsr/Signal/General/dsp/ChanPolSelect.h

#ifndef __dsp_ChanPolSelect_h
#define __dsp_ChanPolSelect_h

#include "dsp/Transformation.h"
#include "dsp/TimeSeries.h"

#include <vector>

namespace dsp
{
  /**
   * @brief ChanPolSelect Transformation that selects the specified,
   * contiguous channels and polarisations from the input, writing to the output.
   */
  class ChanPolSelect : public Transformation<TimeSeries,TimeSeries>
  {

  public:

    //! Default constructor
    ChanPolSelect ();

    //! Destructor
    ~ChanPolSelect () = default;

    void prepare ();

    /**
     * @brief Copy a block of data from the input container
     *  using the following parameters:
     *    start_channel_index
     *    number_of_channels_to_keep
     *    start_polarization_index
     *    number_of_polarizations_to_keep
     */
    void transformation ();

    //! set the start_channel_index
    void set_start_channel_index(unsigned channel_index);

    //! get the start_channel_index
    unsigned get_start_channel_index() const;

    //! set the number_of_channels_to_keep
    void set_number_of_channels_to_keep(unsigned nchan);

    //! get the number_of_channels_to_keep
    unsigned get_number_of_channels_to_keep() const;

    //! set the start_polarization_index
    void set_start_polarization_index(unsigned polarization_index);

    //! get the start_polarization_index
    unsigned get_start_polarization_index() const;

    //! set the number_of_polarizations_to_keep
    void set_number_of_polarizations_to_keep(unsigned npol);

    //! get the number_of_polarizations_to_keep
    unsigned get_number_of_polarizations_to_keep() const;

    //! Alternative implementation
    class Engine;

    //! Set the alternative implementation
    void set_engine (Engine*);

  private:

    //! Start index of the channels to keep
    unsigned start_channel_index = 0;

    //! Number of channels to keep
    unsigned number_of_channels_to_keep = 0;

    //! Start index of the polarizations to keep
    unsigned start_polarization_index = 0;

    //! Number of polarizations to keep
    unsigned number_of_polarizations_to_keep = 0;

    //! Start index of the weights channels to keep
    unsigned wt_start_channel_index = 0;

    //! Number of weights channels to keep
    unsigned wt_number_of_channels_to_keep = 1;

    //! Start index of the weights polarizations to keep
    unsigned wt_start_polarization_index = 0;

    //! Number of weights polarizations to keep
    unsigned wt_number_of_polarizations_to_keep = 1;

    //! The optional alternative implementation
    Reference::To<Engine> engine;
  };

  class ChanPolSelect::Engine : public OwnStream
  {
  public:

    //! Perform any internal setup
    virtual void setup (ChanPolSelect* user);

    //! Copies the selected frequency channels and polarizations for FPT or TFP ordered data
    virtual void select (const dsp::TimeSeries * in, dsp::TimeSeries * out) = 0;

  protected:
  
    //! Start index of the channels to keep.
    unsigned start_channel_index = 0;

    //! Number of channels to keep.
    unsigned number_of_channels_to_keep = 0;

    //! Start index of the polarizations to keep.
    unsigned start_polarization_index = 0;

    //! Number of polarizations to keep.
    unsigned number_of_polarizations_to_keep = 0;
  };

} // namespace dsp

#endif // __dsp_ChanPolSelect_h
